package imp

import (
	sqlc "bgs/db/sqlc"
	afterSaleGrpc "bgs/grpc/gen/service/after_sale"
	"bgs/grpc/gen/shared/message"
	"bgs/grpc/imp/enums"
	"bgs/service/model"
	"bgs/util"
	"encoding/json"
	"context"
	"strconv"
)

/****************************************************************************************/
/*                               after_saleOfS entity of helper                         */
/****************************************************************************************/


func transformAfterSaleItemForSEntityToPb(afterSaleDetails []sqlc.AfterSaleDetail) func(sqlc.ListAfterSaleWithOrderExtAndBuyerInfosAsSpokesmanSearcherRow) *afterSaleGrpc.AfterSaleItemForSEntity {
	return func(o sqlc.ListAfterSaleWithOrderExtAndBuyerInfosAsSpokesmanSearcherRow) *afterSaleGrpc.AfterSaleItemForSEntity {
		orderExtInfo := &model.OrderExtInfo{}
		json.Unmarshal(o.OrderExtInfo, orderExtInfo)

		afterSaleDetailsMap := make(AfterSaleProductSpecKeyToQuantityMap)
		util.Each(util.ToGenericSlice(afterSaleDetails), func(v interface{}) {
			val := v.(sqlc.AfterSaleDetail)
			k := genAfterSaleProductSpecKeyToQuantityMapKey(val.AfterSaleID, val.ProductSpecKey)
			afterSaleDetailsMap[k] = val.Quantity
		})

		var afterSaleDetailInfo []*model.OrderDetailInExtInfo
		util.Each(util.ToGenericSlice(orderExtInfo.Details), func(v interface{}) {
			val := v.(*model.OrderDetailInExtInfo)
			k := genAfterSaleProductSpecKeyToQuantityMapKey(o.ID, val.ProductSpecKey)
			if afterSaleQuantity, ok := afterSaleDetailsMap[k]; ok {
				val.Quantity = afterSaleQuantity
				afterSaleDetailInfo = append(afterSaleDetailInfo, val)
			}
		})

		return &afterSaleGrpc.AfterSaleItemForSEntity{
			Id:                   o.ID,
			Applied:              sqlc.GoTimeToPBTimestamp(o.Applied),
			SerialNumber:         o.SerialNumber,
			BrandId:              o.BrandID,
			ActivityId:           o.ActivityID,
			SpokesmanId:          o.SpokesmanID.Int64,
			SpokesmanUserId:      o.SpokesmanUserID.Int64,
			AfterSaleStatus:      o.AfterSaleStatus,
			Amount:               o.Amount,
			Type:                 o.Type,
			CloseReason:          o.CloseReason.String,
			AfterSaleSlimDetails: mapAfterSaleSlimDetailEntityToPb(afterSaleDetailInfo, transformAfterSaleSlimDetailEntityToPb),
			BrandName:            orderExtInfo.BrandName,
			BrandPic:             orderExtInfo.BrandPic,
			BrandTel:             orderExtInfo.BrandTel,
			ActivityName:         orderExtInfo.ActivityName,
			ActivityTel:          orderExtInfo.ActivityTel,
			BuyerNickName:        orderExtInfo.BuyerNickName,
			BuyerPic:             orderExtInfo.BuyerPic,
		}
	}
}

func mapAfterSaleItemForSEntityToPb(list []sqlc.ListAfterSaleWithOrderExtAndBuyerInfosAsSpokesmanSearcherRow, f func(sqlc.ListAfterSaleWithOrderExtAndBuyerInfosAsSpokesmanSearcherRow) *afterSaleGrpc.AfterSaleItemForSEntity) []*afterSaleGrpc.AfterSaleItemForSEntity {
	r := make([]*afterSaleGrpc.AfterSaleItemForSEntity, len(list))
	for i, item := range list {
		r[i] = f(item)
	}
	return r
}

/****************************************************************************************/
/*                               after_saleOfS entity of query                          */
/****************************************************************************************/


// ListAfterSaleItemsForS 分页获取多个售后单(视角S)
func (s *AfterSaleAPIService) ListAfterSaleItemsForS(ctx context.Context, req *afterSaleGrpc.ListAfterSaleItemsForSRequest) (res *afterSaleGrpc.ListAfterSaleItemsForSResponse, err error) {
	slog := s.NewContextLogger(ctx)
	slog.Infof("after_saleOfS->ListAfterSaleItemsForS:%v", req)

	res = &afterSaleGrpc.ListAfterSaleItemsForSResponse{
		OpRet: &message.OperationResult{
			Success: true,
			Code:    0,
		},
	}

	q := s.dao.Q
	ts := sqlc.PBTimestampToGoTime(req.Ts)
	userID := req.UserId
	if userID == 0 {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     "无效的代言人用户id",
		}
		return
	}
	searchTerm := req.SearchTerm
	if !(searchTerm == "" || searchTerm == string(enums.SearchTermActivity) || searchTerm == string(enums.SearchTermBrand)) {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     "searchTerm不支持",
		}
		return
	}

	var searchValue int64
	if req.SearchValue != "" {
		searchValue, err = strconv.ParseInt(req.SearchValue, 10, 64)
		if err != nil {
			res.OpRet = &message.OperationResult{
				Success: false,
				Code:    400,
				Msg:     err.Error(),
			}
			return
		}
	}

	total, err := q.CountAfterSaleWithOrderExtAndBuyerInfosAsSpokesmanSearcher(ctx, sqlc.CountAfterSaleWithOrderExtAndBuyerInfosAsSpokesmanSearcherParams{
		Created:         ts,
		SpokesmanUserID: sqlc.NInt64FromInt64(userID),
		SearchTerm:      searchTerm,
		SearchValue:     searchValue,
	})
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}

	if total == 0 {
		// 不用继续调用listfunc
		return
	}

	afterSaleItemsForS, err := q.ListAfterSaleWithOrderExtAndBuyerInfosAsSpokesmanSearcher(ctx, sqlc.ListAfterSaleWithOrderExtAndBuyerInfosAsSpokesmanSearcherParams{
		Limit:           req.Limit,
		Offset:          req.Offset,
		Created:         ts,
		SpokesmanUserID: sqlc.NInt64FromInt64(userID),
		SearchTerm:      searchTerm,
		SearchValue:     searchValue,
	})
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}

	afterSaleIDs := util.MapToInt64(util.ToGenericSlice(afterSaleItemsForS), func(v interface{}) int64 {
		val := v.(sqlc.ListAfterSaleWithOrderExtAndBuyerInfosAsSpokesmanSearcherRow)
		return val.ID
	})

	afterSaleDetails, err := q.ListNormalAfterSaleDetailsByAfterSaleIDs(ctx, afterSaleIDs)
	if err != nil {
		res.OpRet = &message.OperationResult{
			Success: false,
			Code:    400,
			Msg:     err.Error(),
		}
		return
	}

	res.Total = total
	res.AfterSaleItemsForS = mapAfterSaleItemForSEntityToPb(afterSaleItemsForS, transformAfterSaleItemForSEntityToPb(afterSaleDetails))
	return

}